package com.yunyao.framework.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunyao.client.request.DeptRequest;
import com.yunyao.client.request.OrgRequest;
import com.yunyao.client.request.PageRequest;
import com.yunyao.client.response.DeptResponse;
import com.yunyao.client.response.OrgResponse;
import com.yunyao.client.service.MdmClientService;
import com.yunyao.common.constant.enums.DataDeletedStatus;
import com.yunyao.common.dto.DeptTreeDto;
import com.yunyao.common.utils.DictCacheUtils;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.PageResult;
import com.yunyao.common.web.util.YResult;
import com.yunyao.dao.model.BamuSysDept;
import com.yunyao.dao.model.custom.DeptChildCountDAO;
import com.yunyao.dao.service.bamu.IBamuSysDeptService;
import com.yunyao.framework.dto.dept.DeptDeleteDto;
import com.yunyao.framework.dto.dept.DeptSaveDto;
import com.yunyao.framework.dto.dept.DeptUpdateDto;
import com.yunyao.framework.service.DeptService;
import com.yunyao.framework.vo.dept.DeptTreeVO;
import com.yunyao.framework.vo.dept.DeptVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author xingjishuai
 * @date 2024-07-16
 */
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private MdmClientService mdmClientService;
    @Autowired
    private IBamuSysDeptService iBamuSysDeptService;


    @Override
    public YResult<List<DeptTreeVO>> treeList(DeptTreeDto deptTreeDto) {
        String parentId = deptTreeDto.getParentId();
        LambdaQueryWrapper<BamuSysDept> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BamuSysDept::getIsDeleted, DataDeletedStatus.NO.getType());
        wrapper.like(StringUtils.isNotEmpty(deptTreeDto.getDeptName()), BamuSysDept::getDeptName, deptTreeDto.getDeptName());
        wrapper.like(StringUtils.isNotEmpty(deptTreeDto.getShortName()), BamuSysDept::getShortName,
                deptTreeDto.getShortName());
        if (StringUtils.isBlank(parentId) || "0".equals(parentId)) {
            wrapper.eq(BamuSysDept::getParentId, 0);
            wrapper.eq(BamuSysDept::getTenantId, "000000");
            wrapper.eq(BamuSysDept::getDeptCategory, "1");
        } else {
            wrapper.eq(BamuSysDept::getParentId, parentId);
        }
        wrapper.orderByAsc(BamuSysDept::getSort);
        wrapper.orderByAsc(BamuSysDept::getId);
        List<BamuSysDept> list = iBamuSysDeptService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return YResult.success(Lists.newArrayList());
        }
        List<DeptTreeVO> voList = daoListToVoTree(list);
        return YResult.success(voList);
    }

    @Override
    public YResult<PageResult<DeptVO>> pageList(DeptTreeDto deptTreeDto) {
        String parentId = deptTreeDto.getParentId();
        LambdaQueryWrapper<BamuSysDept> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BamuSysDept::getIsDeleted, DataDeletedStatus.NO.getType());
        wrapper.like(StringUtils.isNotEmpty(deptTreeDto.getDeptName()), BamuSysDept::getDeptName, deptTreeDto.getDeptName());
        wrapper.like(StringUtils.isNotEmpty(deptTreeDto.getShortName()), BamuSysDept::getShortName,
                deptTreeDto.getShortName());
        if (StringUtils.isBlank(parentId) || "0".equals(parentId)) {
            wrapper.eq(BamuSysDept::getParentId, 0);
            wrapper.eq(BamuSysDept::getTenantId, "000000");
            wrapper.eq(BamuSysDept::getDeptCategory, "1");
        } else {
            wrapper.eq(StringUtils.isNotEmpty(deptTreeDto.getParentId()),BamuSysDept::getParentId, parentId);
        }
        wrapper.orderByAsc(BamuSysDept::getSort);
        wrapper.orderByAsc(BamuSysDept::getId);
        List<BamuSysDept> list = iBamuSysDeptService.list(wrapper);
        if (CollectionUtils.isEmpty(list)) {
            return YResult.success(new PageResult<>());
        }
        List<DeptVO> voList = daoListToVo(list);

        // 分页查询
        IPage<BamuSysDept> page = new Page<>(deptTreeDto.getPageIndex(), deptTreeDto.getPageSize());
        page = iBamuSysDeptService.page(page,wrapper);
        // 处理查询结果
        if(CollectionUtils.isEmpty(page.getRecords())){
            return YResult.success(new PageResult<>());
        }
        return YResult.success(new PageResult<>(voList,page));
    }

    @Override
    public YResult<DeptVO> getDetailInfo(DeptTreeDto deptTreeDto) {
        if (StringUtils.isEmpty(deptTreeDto.getId())) {
            return YResult.error("参数错误");
        }
        BamuSysDept bamuSysDept = iBamuSysDeptService.getById(deptTreeDto.getId());
        if (bamuSysDept == null) {
            return YResult.error("信息不存在");
        }
        return YResult.success(this.daoToVo(bamuSysDept));
    }

    @Override
    public YResult<String> add(DeptSaveDto saveDto) {
        try {
            BamuSysDept sysDept = new BamuSysDept();
            BeanUtils.copyProperties(saveDto, sysDept);
            sysDept.setOrgClass("owner");
            sysDept.setIsOwner(1);
            sysDept.setShowed(true);
            sysDept.setLegalUnit(false);
            iBamuSysDeptService.save(sysDept);
            return YResult.success(sysDept.getId());
        }catch (Exception e) {
            log.error("新增部门失败", e);
            return YResult.error("新增部门失败");
        }
    }

    @Override
    public YResult<String> update(DeptUpdateDto updateDto) {
        try {
            String id = updateDto.getId();
            if (StringUtils.isBlank(id)) {
                return YResult.error("参数错误");
            }
            BamuSysDept oldDept =  iBamuSysDeptService.getById(id);
            if (Objects.isNull(oldDept)) {
                return YResult.error("信息不存在");
            }
            BamuSysDept sysDept = new BamuSysDept();
            BeanUtils.copyProperties(updateDto, sysDept);
            iBamuSysDeptService.updateById(sysDept);
            return YResult.success(sysDept.getId());
        }catch (Exception e) {
            log.error("修改部门失败", e);
            return YResult.error("修改部门失败");
        }
    }

    @Override
    public YResult<String> delete(DeptDeleteDto deleteDto) {
        try {
            String id = deleteDto.getId();
            if (StringUtils.isBlank(id)) {
                return YResult.error("参数错误");
            }
            BamuSysDept oldDept =  iBamuSysDeptService.getById(id);
            if (Objects.isNull(oldDept)) {
                return YResult.error("信息不存在");
            }
            iBamuSysDeptService.deleteById(id);
            return YResult.success(id);
        }catch (Exception e) {
            log.error("删除部门失败", e);
            return YResult.error("删除部门失败");
        }
    }

    @Override
    public YResult<String> sync() {
        try {
            syncOrg();
            syncDept();
            return YResult.success();
        } catch (Exception ex) {
            log.error("同步部门信息失败", ex);
            return YResult.error("同步部门信息失败");
        }
    }

    private void syncDept() {
        List<DeptResponse> records = new ArrayList<>();
        DeptRequest deptRequest = new DeptRequest();
        long pageIndex = 1L;
        do {
            PageRequest pageRequest = new PageRequest();
            pageRequest.setPageIndex(pageIndex);
            pageRequest.setPageSize(100L);
            PageResult<DeptResponse> responsePageResult =
                    mdmClientService.deptPageList(deptRequest, pageRequest);
            records = responsePageResult.getRecords();
            if (CollectionUtils.isEmpty(records) || pageIndex > responsePageResult.getTotalPages()) {
                break;
            }
            for (DeptResponse deptResponse : records) {
                String name = deptResponse.getName();
                BamuSysDept byNameDept = iBamuSysDeptService.getByNameDept(name);
                if (Objects.nonNull(byNameDept)) {
                    continue;
                }
                BamuSysDept sysDept = new BamuSysDept();
                String code = deptResponse.getCode();
                String parentCode = deptResponse.getParentCode();
                String parentName = deptResponse.getParentName();
                if (StringUtils.isBlank(parentName)) {
                    continue;
                }
                sysDept.setTenantId("000000");
                BamuSysDept parentDept = iBamuSysDeptService.getByNameDept(parentName);
                if (Objects.nonNull(parentDept)) {
                    sysDept.setParentId(parentDept.getId());
                    sysDept.setAncestors(parentDept.getAncestors() + parentDept.getId() + ",");
                    sysDept.setDeptCategory(parentDept.getDeptCategory() + 1);
                    sysDept.setDeptLevel(parentDept.getDeptCategory() + 1);
                } else {
                    sysDept.setParentId("0");
                    sysDept.setAncestors("0,");
                    sysDept.setDeptCategory(1);
                    sysDept.setDeptLevel(1);
                }
                sysDept.setDeptCode(code);
                sysDept.setDeptName(name);
                sysDept.setParentCode(parentCode);
                sysDept.setShortName(deptResponse.getShortName());
                sysDept.setOrgType("部门");
                sysDept.setOrgClass("owner");
                sysDept.setShowed(true);
                sysDept.setSyncDeptId(code);
                iBamuSysDeptService.save(sysDept);
            }
            pageIndex++;
        } while (CollectionUtils.isNotEmpty(records));
    }

    private void syncOrg() {
        List<OrgResponse> records = new ArrayList<>();
        OrgRequest orgRequest = new OrgRequest();
        long pageIndex = 1L;
        do {
            PageRequest pageRequest = new PageRequest();
            pageRequest.setPageIndex(pageIndex);
            pageRequest.setPageSize(100L);
            PageResult<OrgResponse> responsePageResult = mdmClientService.orgPageList(orgRequest,
                    pageRequest);
            records = responsePageResult.getRecords();
            if (CollectionUtils.isEmpty(records) || pageIndex > responsePageResult.getTotalPages()) {
                break;
            }
            for (OrgResponse orgResponse : records) {
                String name = orgResponse.getName();
                BamuSysDept byNameDept = iBamuSysDeptService.getByNameOrg(name);
                if (Objects.nonNull(byNameDept)) {
                    continue;
                }
                BamuSysDept sysDept = new BamuSysDept();
                String code = orgResponse.getCode();
                String parentCode = orgResponse.getParentCode();
                String parentName = orgResponse.getParentName();
                if (StringUtils.isBlank(parentName)) {
                    continue;
                }
                sysDept.setTenantId("000000");
                BamuSysDept parentDept = iBamuSysDeptService.getByNameOrg(parentName);
                if (Objects.nonNull(parentDept)) {
                    sysDept.setParentId(parentDept.getId());
                    sysDept.setAncestors(parentDept.getAncestors() + parentDept.getId() + ",");
                    sysDept.setDeptCategory(parentDept.getDeptCategory() + 1);
                    sysDept.setDeptLevel(parentDept.getDeptCategory() + 1);
                } else {
                    sysDept.setParentId("0");
                    sysDept.setAncestors("0,");
                    sysDept.setDeptCategory(1);
                    sysDept.setDeptLevel(1);
                }
                sysDept.setDeptCode(code);
                sysDept.setDeptName(name);
                sysDept.setParentCode(parentCode);
                sysDept.setShortName(orgResponse.getShortName());
                sysDept.setOrgType("组织");
                sysDept.setOrgClass("owner");
                sysDept.setShowed(true);
                sysDept.setSyncDeptId(code);
                iBamuSysDeptService.save(sysDept);
            }
            pageIndex++;
        } while (CollectionUtils.isNotEmpty(records));

    }

    private List<DeptVO> daoListToVo(List<BamuSysDept> list) {
        return list.stream().map(this::daoToVo).collect(Collectors.toList());
    }
    private DeptVO daoToVo(BamuSysDept bamuSysDept) {
        if (bamuSysDept == null){
            return null;
        }
        DeptVO deptVO = new DeptVO();
        BeanUtils.copyProperties(bamuSysDept, deptVO);
        deptVO.setDeptType(DictCacheUtils.getDictValue("org_category", ConvertUtil.null2String(bamuSysDept.getDeptCategory())));
        deptVO.setDeptCategoryName(DictCacheUtils.getDictValue("org_category", ConvertUtil.null2String(bamuSysDept.getDeptCategory())));
        return deptVO;
    }

    private List<DeptTreeVO> daoListToVoTree(List<BamuSysDept> list) {
        List<String> idList = list.stream().map(BamuSysDept::getId).distinct().toList();
        if (CollectionUtils.isEmpty(idList)) {
            return Lists.newArrayList();
        }
        List<DeptChildCountDAO> childCountList = iBamuSysDeptService.childCountByIds(idList);
        Map<String, DeptChildCountDAO> childCountMap = childCountList.stream().collect(Collectors.toMap(DeptChildCountDAO::getParentId, Function.identity(), (a, b) -> a));
        return list.stream().map(x -> this.daoToVoTree(x, childCountMap)).collect(Collectors.toList());
    }

    private DeptTreeVO daoToVoTree(BamuSysDept bamuSysDept, Map<String, DeptChildCountDAO> childCountMap) {
        DeptTreeVO deptTreeVO = new DeptTreeVO();
        BeanUtils.copyProperties(bamuSysDept, deptTreeVO);
        String id = bamuSysDept.getId();
        deptTreeVO.setHasChildren(childCountMap.containsKey(id));
        deptTreeVO.setDeptCategoryName(DictCacheUtils.getDictValue("org_category", ConvertUtil.null2String(bamuSysDept.getDeptCategory())));
        return deptTreeVO;
    }
}
